package com.leon.datalink.core.persistence;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.util.List;

/**
 * 生产级性能优化器
 * 
 * 提供企业级的性能优化功能，包括：
 * - 多级缓存机制
 * - 内存管理优化
 * - 智能预加载策略
 * - 连接池优化
 * - GC压力监控和优化
 * 
 * @author DataLink Team
 * @version 1.0.0
 */
public class ProductionPerformanceOptimizer {
    
    private static final Logger logger = LoggerFactory.getLogger(ProductionPerformanceOptimizer.class);
    
    private static volatile ProductionPerformanceOptimizer instance;
    
    // 性能监控指标
    private final LongAdder cacheHits = new LongAdder();
    private final LongAdder cacheMisses = new LongAdder();
    private final LongAdder memoryOptimizations = new LongAdder();
    private final AtomicLong lastGcTime = new AtomicLong(0);
    
    // 多级缓存
    private final Map<String, Object> l1Cache = new ConcurrentHashMap<>(); // 内存缓存
    private final Map<String, CacheEntry> l2Cache = new ConcurrentHashMap<>(); // 持久化缓存
    
    // 连接池管理
    private final ExecutorService optimizationExecutor;
    private final ScheduledExecutorService monitoringExecutor;
    
    // 配置参数
    private volatile int maxCacheSize = 10000;
    private volatile long cacheExpirationMs = 300000; // 5分钟
    private volatile double gcPressureThreshold = 0.8;
    private volatile int preloadBatchSize = 100;
    
    private ProductionPerformanceOptimizer() {
        this.optimizationExecutor = Executors.newFixedThreadPool(
            Runtime.getRuntime().availableProcessors(),
            r -> {
                Thread t = new Thread(r, "performance-optimizer-" + System.currentTimeMillis());
                t.setDaemon(true);
                return t;
            }
        );
        
        this.monitoringExecutor = Executors.newScheduledThreadPool(2,
            r -> {
                Thread t = new Thread(r, "performance-monitor-" + System.currentTimeMillis());
                t.setDaemon(true);
                return t;
            }
        );
        
        initializeOptimizer();
        logger.info("生产级性能优化器初始化完成");
    }
    
    public static ProductionPerformanceOptimizer getInstance() {
        if (instance == null) {
            synchronized (ProductionPerformanceOptimizer.class) {
                if (instance == null) {
                    instance = new ProductionPerformanceOptimizer();
                }
            }
        }
        return instance;
    }
    
    /**
     * 初始化优化器
     */
    private void initializeOptimizer() {
        // 启动内存监控
        monitoringExecutor.scheduleAtFixedRate(this::monitorMemoryUsage, 0, 30, TimeUnit.SECONDS);
        
        // 启动GC监控
        monitoringExecutor.scheduleAtFixedRate(this::monitorGarbageCollection, 0, 10, TimeUnit.SECONDS);
        
        // 启动缓存清理
        monitoringExecutor.scheduleAtFixedRate(this::cleanupExpiredCache, 0, 60, TimeUnit.SECONDS);
        
        logger.info("性能监控任务已启动");
    }
    
    /**
     * 多级缓存获取
     */
    public <T> T getCachedValue(String key, Class<T> type) {
        // L1缓存查找
        Object value = l1Cache.get(key);
        if (value != null) {
            cacheHits.increment();
            return type.cast(value);
        }
        
        // L2缓存查找
        CacheEntry entry = l2Cache.get(key);
        if (entry != null && !entry.isExpired()) {
            // 提升到L1缓存
            l1Cache.put(key, entry.getValue());
            cacheHits.increment();
            return type.cast(entry.getValue());
        }
        
        cacheMisses.increment();
        return null;
    }
    
    /**
     * 多级缓存存储
     */
    public void putCachedValue(String key, Object value) {
        // 检查缓存大小限制
        if (l1Cache.size() >= maxCacheSize) {
            // 清理最老的条目
            cleanupOldestEntries();
        }
        
        l1Cache.put(key, value);
        l2Cache.put(key, new CacheEntry(value, System.currentTimeMillis() + cacheExpirationMs));
    }
    
    /**
     * 智能预加载
     */
    public CompletableFuture<Void> preloadData(String pattern, DataLoader loader) {
        return CompletableFuture.runAsync(() -> {
            try {
                logger.debug("开始预加载数据，模式: {}", pattern);
                
                List<String> keys = loader.getKeysForPattern(pattern);
                int batchCount = (keys.size() + preloadBatchSize - 1) / preloadBatchSize;
                
                for (int i = 0; i < batchCount; i++) {
                    int start = i * preloadBatchSize;
                    int end = Math.min(start + preloadBatchSize, keys.size());
                    List<String> batch = keys.subList(start, end);
                    
                    // 批量加载
                    Map<String, Object> batchData = loader.loadBatch(batch);
                    batchData.forEach(this::putCachedValue);
                }
                
                logger.info("预加载完成，加载了 {} 个数据项", keys.size());
            } catch (Exception e) {
                logger.error("预加载数据失败", e);
            }
        }, optimizationExecutor);
    }
    
    /**
     * 内存使用监控
     */
    private void monitorMemoryUsage() {
        try {
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            long usedMemory = memoryBean.getHeapMemoryUsage().getUsed();
            long maxMemory = memoryBean.getHeapMemoryUsage().getMax();
            
            double memoryUsageRatio = (double) usedMemory / maxMemory;
            
            if (memoryUsageRatio > gcPressureThreshold) {
                logger.warn("内存使用率过高: {:.2f}%, 触发优化", memoryUsageRatio * 100);
                optimizeMemoryUsage();
            }
            
            logger.debug("内存使用情况 - 已用: {}MB, 最大: {}MB, 使用率: {:.2f}%", 
                usedMemory / 1024 / 1024, maxMemory / 1024 / 1024, memoryUsageRatio * 100);
        } catch (Exception e) {
            logger.error("内存监控失败", e);
        }
    }
    
    /**
     * GC监控
     */
    private void monitorGarbageCollection() {
        try {
            List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
            long totalGcTime = 0;
            
            for (GarbageCollectorMXBean gcBean : gcBeans) {
                totalGcTime += gcBean.getCollectionTime();
            }
            
            long lastTime = lastGcTime.get();
            if (totalGcTime > lastTime) {
                long gcDelta = totalGcTime - lastTime;
                if (gcDelta > 1000) { // GC时间超过1秒
                    logger.warn("GC压力过大，耗时: {}ms", gcDelta);
                    optimizeMemoryUsage();
                }
                lastGcTime.set(totalGcTime);
            }
        } catch (Exception e) {
            logger.error("GC监控失败", e);
        }
    }
    
    /**
     * 内存优化
     */
    private void optimizeMemoryUsage() {
        optimizationExecutor.submit(() -> {
            try {
                // 清理过期缓存
                cleanupExpiredCache();
                
                // 压缩L1缓存
                if (l1Cache.size() > maxCacheSize / 2) {
                    int toRemove = l1Cache.size() - maxCacheSize / 2;
                    l1Cache.entrySet().stream()
                        .limit(toRemove)
                        .map(Map.Entry::getKey)
                        .forEach(l1Cache::remove);
                }
                
                // 建议GC
                System.gc();
                
                memoryOptimizations.increment();
                logger.info("内存优化完成，L1缓存大小: {}, L2缓存大小: {}", l1Cache.size(), l2Cache.size());
            } catch (Exception e) {
                logger.error("内存优化失败", e);
            }
        });
    }
    
    /**
     * 清理过期缓存
     */
    private void cleanupExpiredCache() {
        long now = System.currentTimeMillis();
        l2Cache.entrySet().removeIf(entry -> entry.getValue().isExpired(now));
    }
    
    /**
     * 清理最老的缓存条目
     */
    private void cleanupOldestEntries() {
        int toRemove = l1Cache.size() - maxCacheSize + 100; // 多清理一些
        l1Cache.entrySet().stream()
            .limit(toRemove)
            .map(Map.Entry::getKey)
            .forEach(l1Cache::remove);
    }
    
    /**
     * 获取性能统计
     */
    public PerformanceStats getPerformanceStats() {
        long hits = cacheHits.sum();
        long misses = cacheMisses.sum();
        double hitRate = hits + misses > 0 ? (double) hits / (hits + misses) : 0.0;
        
        return new PerformanceStats(
            hits, misses, hitRate,
            l1Cache.size(), l2Cache.size(),
            memoryOptimizations.sum()
        );
    }
    
    /**
     * 关闭优化器
     */
    public void shutdown() {
        try {
            monitoringExecutor.shutdown();
            optimizationExecutor.shutdown();
            
            if (!monitoringExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                monitoringExecutor.shutdownNow();
            }
            if (!optimizationExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                optimizationExecutor.shutdownNow();
            }
            
            logger.info("生产级性能优化器已关闭");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("关闭优化器时被中断", e);
        }
    }
    
    /**
     * 缓存条目
     */
    private static class CacheEntry {
        private final Object value;
        private final long expirationTime;
        
        public CacheEntry(Object value, long expirationTime) {
            this.value = value;
            this.expirationTime = expirationTime;
        }
        
        public Object getValue() {
            return value;
        }
        
        public boolean isExpired() {
            return isExpired(System.currentTimeMillis());
        }
        
        public boolean isExpired(long now) {
            return now > expirationTime;
        }
    }
    
    /**
     * 数据加载器接口
     */
    public interface DataLoader {
        List<String> getKeysForPattern(String pattern);
        Map<String, Object> loadBatch(List<String> keys);
    }
    
    /**
     * 性能统计
     */
    public static class PerformanceStats {
        private final long cacheHits;
        private final long cacheMisses;
        private final double hitRate;
        private final int l1CacheSize;
        private final int l2CacheSize;
        private final long memoryOptimizations;
        
        public PerformanceStats(long cacheHits, long cacheMisses, double hitRate,
                              int l1CacheSize, int l2CacheSize, long memoryOptimizations) {
            this.cacheHits = cacheHits;
            this.cacheMisses = cacheMisses;
            this.hitRate = hitRate;
            this.l1CacheSize = l1CacheSize;
            this.l2CacheSize = l2CacheSize;
            this.memoryOptimizations = memoryOptimizations;
        }
        
        // Getters
        public long getCacheHits() { return cacheHits; }
        public long getCacheMisses() { return cacheMisses; }
        public double getHitRate() { return hitRate; }
        public int getL1CacheSize() { return l1CacheSize; }
        public int getL2CacheSize() { return l2CacheSize; }
        public long getMemoryOptimizations() { return memoryOptimizations; }
        
        @Override
        public String toString() {
            return String.format("PerformanceStats{hits=%d, misses=%d, hitRate=%.2f%%, " +
                "l1Size=%d, l2Size=%d, optimizations=%d}",
                cacheHits, cacheMisses, hitRate * 100, l1CacheSize, l2CacheSize, memoryOptimizations);
        }
    }
}
